#ifndef XGE_XWORKER_KIILABLE_QUEUE_H_
#define XGE_XWORKER_KIILABLE_QUEUE_H_
#include "xge_common_config.h"
#include "xworker_queue.h"
#include "xkillable_task.h"
#include "xsync.h"
#include "xloop_sync.h"
#include "xthread_delegate.h"
#include "xthread.h"
#include "xthread_manager.h"


namespace xge {
namespace xge_internal{
  // A killable queue 
  // This queue will internally use a MAP as the internal storage data structure
  // and delete the target element by using a KEY , which is the XString class .
  class WorkerSingleQueue : public WorkerQueue ,  public LoopSync {
  public: // Virtual derive function implementation
    // Push
    virtual bool PushTask( const TaskPtr& task_ptr );
    typedef WorkerQueue::TaskPtrList TaskPtrList;
    virtual size_t PushTask( TaskPtrList* task_list );
    virtual bool TryPushTask( const TaskPtr& task_ptr );
    // Wait
    virtual bool WaitWhenRelease();
    virtual bool WaitWhenEmpty  ();
    virtual const TripleResult WaitWhenRelease( int ms );
    virtual const TripleResult WaitWhenEmpty  ( int ms );
    // Post 
    inline virtual void PostQuitSoon();
    inline virtual void PostQuitWhenEmpty();
    // Loop synchronization
    inline virtual void LoopTicking( const Timer::tick_t& diff_time );
    inline WorkerSingleQueue();
  public: // Specialization function implementation for this special implementation of worker queue
    // Erase a specific target task when it is not Locking or Executing 
    bool KillTask( const String& task_key );
    inline void Clear();
  public: // Special type of attribute function
    bool empty() const {
      return queue_.empty();
    }
    size_t size() const {
      return queue_.size();
    }

  public:
    // Loop
    virtual int Loop();
  private:
    typedef xge::vector< TaskPtr >::Vector TaskPtrVector;
    //Dequeue batch operation
    size_t Dequeue( TaskPtrVector* container , size_t size );
    //Wake up the back queue if it is sleeping
    void WakeUp();

  private:
    // Quit type option enumeration
    enum {
      RUNNING,
      QUIT_SOON ,
      QUIT_WHEN_EMPTY
    };
    // Quit type option
    int quit_option_;
    // Queue synchronization lock
    FastLock queue_sync_lock_;
    // Queue sleep lock
    WaitableEvent sleep_lock_;
    // delete times totally
    size_t delete_times_total_;
    // enqueue times totally 
    size_t enqueue_times_total_;
    // loop times
    uint64_t loop_times_;
    // precache size
    size_t precache_size_;
    // internal queue
    typedef xge::map< String , TaskPtr >::Map QueueType;
    QueueType queue_;
    // max precache queue size 
    static const size_t kMaxPrecacheSize = 5;
  };


  inline WorkerSingleQueue::WorkerSingleQueue() :
    quit_option_(RUNNING),
    delete_times_total_(0),
    enqueue_times_total_(0),
    loop_times_(0),
    precache_size_(1),
    sleep_lock_(false), // auto set
    WorkerQueue(WorkerQueue::QUEUE_TYPE_SINGLE_QUEUE,REMOTE_BINDING){}

  void WorkerSingleQueue::Clear() {
    AutoLock<FastLock> l(queue_sync_lock_);
    queue_.clear();
  }

  inline void WorkerSingleQueue::PostQuitSoon() {
    set_status( WorkerQueue::STATUS_LOCKING );
    quit_option_ = ( QUIT_SOON );
    WakeUp();
  }

  inline void WorkerSingleQueue::PostQuitWhenEmpty() {
    set_status( WorkerQueue::STATUS_LOCKING );
    quit_option_ = ( QUIT_WHEN_EMPTY );
    WakeUp();
  }

  inline void WorkerSingleQueue::LoopTicking( const Timer::tick_t& diff_time ) {
    ++loop_times_;
    precache_size_ = (size_t)( (delete_times_total_ + enqueue_times_total_)/(loop_times_) );
    if( precache_size_ == 0 )
      precache_size_ = 1;
    if( precache_size_ > kMaxPrecacheSize ) 
      precache_size_ = kMaxPrecacheSize;
  }

  inline void WorkerSingleQueue::WakeUp() {
      sleep_lock_.Notify();
  }

}// namespace xge_internal
}// namespace xge





#endif// XGE_XWORKER_KIILABLE_QUEUE_H_